#pragma once

#ifndef _Terrain_h_
#define _Terrain_h_

#include "HeightMap.h"
#include "TerrainPart.h"
#include "TreePlanter.h"
#include "../../Framework/Mesh.h"
#include "../../Framework/Quadtree.h"
#include "../../Framework/Vertex.h"

#include <vector>

namespace MyGame {

using namespace Framework;
using namespace std;

class TreePlanter;

class Terrain :
            public Mesh {
public:
    Terrain(Game* game);
    virtual ~Terrain(void);
    bool GetDrawPartialTerrain() const;
    void SetDrawPartialTerrain(bool val);
    FLOAT GetHeightGrass() const;
    void SetHeightGrass(FLOAT val);
    FLOAT GetHeightRock() const;
    void SetHeightRock(FLOAT val);
    FLOAT GetHeightSand() const;
    void SetHeightSand(FLOAT val);
    FLOAT GetHeightSnow() const;
    void SetHeightSnow(FLOAT val);
    FLOAT GetHeightWater() const;
    void SetHeightWater(FLOAT val);
    D3DXVECTOR3 GetHeightMapScale() const;
    void SetHeightMapScale(D3DXVECTOR3 val);
    FLOAT GetVisibilityRange() const;
    void SetVisibilityRange(FLOAT val);
    HeightMap* GetHeightMap() const;
    FLOAT GetHeightFromSurface(D3DXVECTOR3 position);
    Quadtree<TerrainPart*>* GetTerrainParts() const;
    void SetDrawUnderwater(bool val);
    void SetHeightMapDimensions(int width, int length);
    virtual void Draw(FLOAT timeDelta);
    virtual void Initialize();
    virtual void LoadContent();
    virtual void UpdateVisibleParts();
private:
    bool drawPartialTerrain;
    bool drawUnderwater;
    HeightMap* heightMap;
    int heightMapLength;
    int heightMapWidth;
    D3DXVECTOR3 heightMapScale;
    FLOAT heightGrass;
    FLOAT heightRock;
    FLOAT heightSand;
    FLOAT heightSnow;
    FLOAT heightWater;
    vector<DWORD>* indices;
    vector<int> normalLookupTable;
    vector<Vertex>* vertices;
    Quadtree<TerrainPart*>* terrainParts;
    IDirect3DTexture9* textureGrass;
    IDirect3DTexture9* textureRock;
    IDirect3DTexture9* textureSand;
    IDirect3DTexture9* textureSnow;
    IDirect3DTexture9* textureWater;
    vector<TreeBase<TerrainPart*>*>* visibleTerrainParts;
    FLOAT visibilityRange;
    virtual void DrawSubset(DWORD attribId);
    void DrawTerrainParts(Quadtree<TerrainPart*>* quadtree);
    void GenerateFaceNormals();
    void GenerateIndices();
    void GenerateNormalLookupTable();
    void GenerateTerrain();
    void GenerateVertices();
    void InitializeMesh();
    void InitializeQuadtree(Quadtree<TerrainPart*>* quadtree);
};

}

#endif
